package com.ndp.fb.rdb.mongo.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.AggregationOptions;
import com.mongodb.BasicDBObject;
import com.mongodb.Cursor;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.ndp.fb.constant.MongoConstants;
import com.ndp.fb.mongo.api.ProductSetMongoService;

@Service
public class ProductSetMongoServiceImpl implements ProductSetMongoService {
	Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private DB mongoDBClientPrimary;

	@Autowired
	private DB pixelDBClient;
	@Override
	public String saveProductSet(JSONObject productSet) {
		String id = null;
		if (productSet.containsKey("id")) {
			id = productSet.getString("id");
		} else {
			id = UUID.randomUUID().toString();
		}
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		DBObject update = (DBObject) com.mongodb.util.JSON.parse(JSONObject.toJSONString(productSet));
		update.put("created_time", new Date());
		dbCollection.update(new BasicDBObject("id", id),
				new BasicDBObject("$set",update), true, false,
				WriteConcern.JOURNALED);
		return id;
	}

	@Override
	public JSONArray getProductSets(JSONObject query) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		DBObject q = (BasicDBObject) com.mongodb.util.JSON.parse(JSONObject.toJSONString(query));
		DBCursor dbCursor = dbCursor = dbCollection.find(q);;
		JSONArray result = new JSONArray();
		if (dbCursor == null) {
			return null;
		}
		DBObject obj;
		while (dbCursor.hasNext()) {
			obj = dbCursor.next();
			result.add(JSONObject.parseObject(JSONObject.toJSONString(obj)));
		}
		return result;
	}

	@Override
	public JSONArray getProductSets(List<DBObject> query) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
		Cursor cursor = dbCollection.aggregate(query, aggregationOptions);

		JSONArray result = new JSONArray();
		if (cursor == null) {
			return null;
		}
		DBObject obj;
		while (cursor.hasNext()) {
			obj = cursor.next();
			result.add(JSONObject.parseObject(JSONObject.toJSONString(obj)));
		}
		return result;
	}

	@Override
	public JSONArray getPixelDataIds(String job_id,String event) {
		DBCollection dbCollection = pixelDBClient.getCollection(MongoConstants.TABLE_NAME_PIXELDATA);
		DBObject q = new BasicDBObject("groupId", job_id).append("event", event);
		DBCursor dbCursor = dbCollection.find(q);
		JSONArray result = new JSONArray();
		if (dbCursor == null) {
			return null;
		}
		DBObject obj;
		while (dbCursor.hasNext()) {
			obj = dbCursor.next();
			result.add(obj.get("content_id_new"));
		}
		return result;
	}
	@Override
	public JSONArray getPixelData(String job_id,String event) {
		DBCollection dbCollection = pixelDBClient.getCollection(MongoConstants.TABLE_NAME_PIXELDATA);
		DBObject q = new BasicDBObject("groupId", job_id).append("event", event);
		DBCursor dbCursor = dbCollection.find(q).sort(new BasicDBObject("actions", -1));
		JSONArray result = new JSONArray();
		if (dbCursor == null) {
			return null;
		}
		DBObject obj;
		while (dbCursor.hasNext()) {
			obj = dbCursor.next();
			result.add(JSONObject.parseObject(JSONObject.toJSONString(obj)));
		}
		return result;
	}
	@Override
	public void updateData(String p_id,int i, int j,JSONArray data,String data_status) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set",
						new BasicDBObject("target_rule.and."+i+".or." + j + ".data", data.toArray())
								.append("target_rule.and."+i+".or." + j + ".data_status", data_status)),
				true, false, WriteConcern.JOURNALED);

	}

	@Override
	public void updateProductSetData(String p_id, String fb_script, List<String> ids, String data_status) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("data", ids.toArray()).append("fb_script", fb_script).append("data_status", data_status)),
				true, false, WriteConcern.JOURNALED);
	}

	@Override
	public JSONArray getProductSets(JSONObject query, Integer pageIndex, Integer pageSize, JSONObject order) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		DBObject q = (DBObject) com.mongodb.util.JSON.parse(JSONObject.toJSONString(query));
		DBCursor dbCursor = dbCollection.find(q).skip((pageIndex - 1) * pageSize).limit(pageSize)
				.sort((DBObject) com.mongodb.util.JSON.parse(JSONObject.toJSONString(order)));
		JSONArray result = new JSONArray();
		if (dbCursor == null) {
			return null;
		}
		DBObject obj;
		while (dbCursor.hasNext()) {
			obj = dbCursor.next();
			result.add(JSONObject.parseObject(JSONObject.toJSONString(obj)));
		}
		return result;
	}

	@Override
	public Long countProductSet(JSONObject query) {
		DBObject match = (DBObject) com.mongodb.util.JSON.parse(JSONObject.toJSONString(query));
		List<DBObject> pipeline = new ArrayList<>();
		pipeline.add(new BasicDBObject("$match", match));
		DBObject group = new BasicDBObject("_id", null);
		group.put("total", new BasicDBObject("$sum", 1));
		pipeline.add(new BasicDBObject("$group", group));

		long start = System.currentTimeMillis();
		AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
		Cursor cursor = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET).aggregate(pipeline,
				aggregationOptions);
		logger.info("Mongo聚合查询花费时间：" + (System.currentTimeMillis() - start) + "毫秒");
		try {
			if (cursor.hasNext()) {
				DBObject dbObject = cursor.next();
				if (dbObject != null && dbObject.get("total") != null) {
					return Long.valueOf(dbObject.get("total").toString());
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			cursor.close();
		}
		return 0L;
	}

	@Override
	public void pushFBProductSetId(String p_id,Long catalog_id, Long fb_pId) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
        DBObject query = new BasicDBObject();
        query.put("id", p_id);
        DBObject update = new BasicDBObject();
        update.put("catalog_id", catalog_id);
        update.put("fb_productset_id", fb_pId);
        update.put("updated_time", new Date());
        dbCollection.update(query, new BasicDBObject("$addToSet", new BasicDBObject("fb_ids", update)), true, false,WriteConcern.JOURNALED);
	}

	@Override
	public void updateProductSetStatus(String p_id, String status) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("status", status)),
				true, false, WriteConcern.JOURNALED);
		
	}

	@Override
	public void updateFBProductSetUpdateTime(String p_id, Long fb_pId) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
        DBObject query = new BasicDBObject();
        query.put("id", p_id);
        query.put("fb_ids.fb_productset_id", fb_pId);
        dbCollection.update(query, new BasicDBObject("$set", new BasicDBObject("fb_ids.$.updated_time", new Date())), true, false,WriteConcern.JOURNALED);
	}

	@Override
	public void updateProductSetDataStatus(Long feed_id, String data_status) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("feed_id", feed_id),
				new BasicDBObject("$set", new BasicDBObject("data_status", data_status)),
				false, true, WriteConcern.JOURNALED);
		
	}
	@Override
	public void updateProductSetReportDataStatus(String p_id,String data_url, String data_status) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("report_data_status", data_status).append("report_data_url", data_url)),
				false, true, WriteConcern.JOURNALED);
		
	}
	@Override
	public void updateProductSetDataUpdatedUuid(String p_id, String data_updated_uuid) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("data_updated_uuid", data_updated_uuid)),
				false, true, WriteConcern.JOURNALED);
	}

	@Override
	public void updateProductSetTargetRule(String p_id, JSONObject target_rule) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("target_rule", target_rule)),
				true, false, WriteConcern.JOURNALED);
		
	}

	@Override
	public JSONObject getPixelData(String group_id, String event, String item_id) {
		DBCollection dbCollection = pixelDBClient.getCollection(MongoConstants.TABLE_NAME_PIXELDATA);
		DBObject q = new BasicDBObject("groupId", group_id).append("event", event).append("content_id_new", item_id);
		DBObject dbobject = dbCollection.findOne(q);
		return JSONObject.parseObject(JSONObject.toJSONString(dbobject));
	}

	@Override
	public void updateProductSetDatePersent(String p_id, Integer date_persent) {
		DBCollection dbCollection = mongoDBClientPrimary.getCollection(MongoConstants.TABLE_NAME_PRODUCTSET);
		dbCollection.update(new BasicDBObject("id", p_id),
				new BasicDBObject("$set", new BasicDBObject("report_data_date_preset", date_persent)),
				true, false, WriteConcern.JOURNALED);
		
	}

}
